import { Application } from "egg";
import * as fs from "fs";
import * as path from "path";
import SequelizeService from "./app/database/sequelize";
import { initModels } from "./app/model/index";

export default class AppBootHook {
  private readonly app: Application;
  private sequelizeService: SequelizeService;

  constructor(app: Application) {
    this.app = app;
    this.sequelizeService = new SequelizeService(app);
  }

  /**
   * 清理日志文件
   */
  private clearLogs() {
    const logsDir = path.join(__dirname, "../logs");

    if (!fs.existsSync(logsDir)) {
      return;
    }

    try {
      this.clearDirectory(logsDir);
      console.log("🧹 启动时日志清理完成");
    } catch (error) {
      console.warn("⚠️  清理日志时出现警告:", error instanceof Error ? error.message : error);
    }
  }

  private clearDirectory(dirPath: string) {
    if (!fs.existsSync(dirPath)) {
      return;
    }

    const files = fs.readdirSync(dirPath);

    files.forEach(file => {
      const filePath = path.join(dirPath, file);
      const stat = fs.statSync(filePath);

      if (stat.isDirectory()) {
        this.clearDirectory(filePath);
      } else if (stat.isFile() && file.endsWith(".log")) {
        fs.unlinkSync(filePath);
      }
    });
  }

  configWillLoad() {
    // 应用配置即将加载
    console.log("应用配置即将加载...");
    // 在应用启动最早期清理日志
    this.clearLogs();
  }

  configDidLoad() {
    // 配置文件加载完成
    console.log("应用配置加载完成");
  }
  
  async didLoad() {
    // 文件加载完成
    console.log("文件加载完成");

    // 初始化Sequelize数据库连接
    try {
      console.log("🔗 初始化Sequelize数据库连接...");
      const sequelize = await this.sequelizeService.init();

      // 初始化所有模型
      const models = initModels(sequelize);

      // 将模型挂载到app上供其他地方使用
      (this.app as any).models = models;
      (this.app as any).sequelize = sequelize;

      console.log("✅ 数据库连接和模型初始化成功");
    } catch (error) {
      console.error("❌ 数据库初始化失败:", error);
      throw error;
    }
  }

  async willReady() {
    // 插件启动完毕
    console.log("插件启动完毕");

    // 同步数据库模型（本地开发与单元测试环境）
    if (this.app.config.env === "local" || this.app.config.env === "unittest") {
      try {
        console.log("🔄 同步数据库模型...");
        await this.sequelizeService.syncModels(false); // 不强制重建表
        console.log("✅ 数据库模型同步完成");

        // 在单元测试环境下，准备基础测试数据
        if (this.app.config.env === "unittest") {
          const { sequelize } = this.app as any;
          try {
            // 确保存在ID为1和2的用户，供文档与协作测试使用
            await sequelize.query("INSERT INTO users (id, username, password_hash, salt, status, login_count, created_at, updated_at) VALUES (1,'inviter','$2a$10$placeholder','salt',1,0,NOW(),NOW()) ON DUPLICATE KEY UPDATE username=VALUES(username)");
            await sequelize.query("INSERT INTO users (id, username, password_hash, salt, status, login_count, created_at, updated_at) VALUES (2,'invitee','$2a$10$placeholder2','salt',1,0,NOW(),NOW()) ON DUPLICATE KEY UPDATE username=VALUES(username)");
            console.log("✅ 单测基础用户就绪: [1: inviter], [2: invitee]");
          } catch (seedErr) {
            console.warn("⚠️  单测基础用户准备失败:", seedErr instanceof Error ? seedErr.message : seedErr);
          }
        }
      } catch (error) {
        console.error("❌ 数据库模型同步失败:", error);
        // 不抛出错误，允许应用继续启动
      }
    }
  }

  async didReady() {
    // 应用启动完成
    console.log("🚀 应用启动完成！");
    console.log(`📍 HTTP服务: http://localhost:${this.app.config.cluster.listen.port}`);
    console.log(`✅ 健康检查: http://localhost:${this.app.config.cluster.listen.port}/health`);
  }

  async serverDidReady() {
    // 服务器启动完成
    console.log("服务器启动完成");

    // 自动初始化 Socket.io 服务
    try {
      // 单元测试环境下不启动 socket 服务，避免端口占用影响用例
      if (this.app.config.env === "unittest") {
        console.log("[unittest] 跳过 Socket.io 初始化");
      } else {
        const ctx = this.app.createAnonymousContext();
        await ctx.service.socket.init();
      }
    } catch (error) {
      console.error("Socket.io 服务初始化失败:", error);
    }
  }

  async beforeClose() {
    // 应用关闭前的清理工作
    console.log("🔒 应用准备关闭，清理资源...");

    try {
      await this.sequelizeService.close();
      console.log("✅ 数据库连接已关闭");
    } catch (error) {
      console.error("❌ 关闭数据库连接时出错:", error);
    }
  }
}
